#include "screenshottool.h"
#include "ui_screenshottool.h"
#include "operateset.hpp"
#include "const.h"

#include <QTranslator>
#include <QSettings>

ScreenShotTool::ScreenShotTool(QWidget *parent) :
    QWidget(parent),
    mpUI(new Ui::ScreenShotTool)
{
    mpUI->setupUi(this);

    auto * tpParent=new QWidget;
    this->setParent(tpParent);

    this->setWindowFlags(Qt::Dialog|Qt::WindowCloseButtonHint|Qt::WindowStaysOnTopHint);
    this->setWindowTitle(tr("Setting"));
    this->setWindowIcon(QIcon(":/ss.icon"));

    this->mpKeystring=new KeyString();

    this->mpSc_set=new HotKeyBar;
    this->mpSc_set->setKeyString(this->mpKeystring);
    this->mpSc_set->setReadOnly(true);

    this->mpUI->gridLayout->addWidget(this->mpSc_set,0,1);
    connect(this->mpSc_set, SIGNAL(sgn_hotKeyChanged(Qt::Key,Qt::KeyboardModifiers)),this,SLOT(slt_changeHotKey(Qt::Key,Qt::KeyboardModifiers)));
    connect(this->mpUI->checkBox,SIGNAL(stateChanged(int)),this,SLOT(slt_auto_run(int)));
    connect(this->mpUI->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(slt_language_set(int)));

    this->initTray();

    auto keyStr=OperateSet::readSetting("HotKey","ScreenShot","CTRL+F1").toString();
    this->mpKeystring->string2Key(keyStr,this->mKey,this->mMods);
    this->mpSc_set->setHotKey(this->mKey,this->mMods);
    this->registerHotKey(this->mKey,this->mMods);

    this->mIsAutoRun=bool(OperateSet::readSetting("Setting","AutoRun",0).toInt());
    this->mpUI->checkBox->setChecked(this->mIsAutoRun);
    this->setAutoRun(this->mIsAutoRun);

    auto language=OperateSet::readSetting("Setting","Language","en").toString();
    this->changeLanguage(language);
    if(language==Const::L_EN){
        this->mpUI->comboBox->setCurrentIndex(0);
    }else{
        this->mpUI->comboBox->setCurrentIndex(1);
    }

    this->setFixedSize(this->size());
}

ScreenShotTool::~ScreenShotTool()
{
    this->unregisterHotKey(this->mKey,this->mMods);
    delete mpUI;
}

void ScreenShotTool::initTray()
{
    this->mpSystemTray=new QSystemTrayIcon(this);
    this->mpSystemTray->setIcon(QIcon(":/ss.ico"));
    this->mpSystemTray->setToolTip("ScreenShot");

    this->mpSetAction=new QAction(tr("Setting"),this);
    this->mpAboutAction=new QAction(tr("About"),this);
    this->mpExitAction=new QAction(tr("Exit"),this);

    auto pTrayMenu = new QMenu(this);
    pTrayMenu->addAction(this->mpSetAction);
    pTrayMenu->addAction(this->mpAboutAction);
    pTrayMenu->addAction(this->mpExitAction);

    this->mpSystemTray->setContextMenu(pTrayMenu);
    this->mpSystemTray->show();

    connect(this->mpSystemTray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(slt_clickTray(QSystemTrayIcon::ActivationReason)));
    connect(this->mpSetAction,SIGNAL(triggered(bool)),this,SLOT(slt_setAction()));
    connect(this->mpAboutAction,SIGNAL(triggered(bool)),this,SLOT(slt_aboutAction()));
    connect(this->mpExitAction,SIGNAL(triggered(bool)),this,SLOT(slt_exitAction()));
}

void ScreenShotTool::changeLanguage(QString lan)
{
    QTranslator translator;
    bool bRes=false;

    if(Const::L_ZH_CN==lan){
        bRes=translator.load(Const::F_L_ZH_CN);
        OperateSet::writeSetting("Setting","Language",Const::L_ZH_CN);
    }else if(Const::L_EN==lan){
        bRes=translator.load(Const::F_L_EN);
        OperateSet::writeSetting("Setting","Language",Const::L_EN);
    }

    if(bRes){
        QApplication::installTranslator(&translator);
        this->mpUI->retranslateUi(this);
        this->reFresh();
    }
}

void ScreenShotTool::reFresh()
{
    this->setWindowTitle(tr("Setting"));;
    this->mpSetAction->setText(tr("Setting"));
    this->mpAboutAction->setText(tr("About"));
    this->mpExitAction->setText(tr("Exit"));
}

void ScreenShotTool::slt_clickTray(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason) {
    case QSystemTrayIcon::Trigger:
        this->ss_start();
        break;
    case QSystemTrayIcon::DoubleClick:
        this->show();
        break;
    default:
        break;
    }
}

void ScreenShotTool::slt_setAction()
{
    this->show();
}

void ScreenShotTool::slt_aboutAction()
{

}

void ScreenShotTool::slt_exitAction()
{
    this->mCloseFlag=true;
    this->close();
    QApplication::quit();
}

void ScreenShotTool::closeEvent(QCloseEvent *event)
{
    if(this->mCloseFlag){
        event->accept();
    }else{
        this->hide();
        event->ignore();
    }
}

bool ScreenShotTool::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
    if("windows_generic_MSG"==eventType||"windows_dispatcher_MSG"==eventType){
        auto pMsg=reinterpret_cast<MSG*>(message);
        if(WM_HOTKEY == pMsg->message){
            if(HIWORD(pMsg->lParam)==nativeKeycode(this->mKey)&&LOWORD(pMsg->lParam)==nativeModifiers(this->mMods)){
                this->ss_start();
            }
        }
    }
    return false;
}

quint32 ScreenShotTool::nativeKeycode(Qt::Key key)                      //key值转换
{
    switch (key)
    {
    case Qt::Key_Escape:
        return VK_ESCAPE;
    case Qt::Key_Tab:
    case Qt::Key_Backtab:
        return VK_TAB;
    case Qt::Key_Backspace:
        return VK_BACK;
    case Qt::Key_Return:
    case Qt::Key_Enter:
        return VK_RETURN;
    case Qt::Key_Insert:
        return VK_INSERT;
    case Qt::Key_Delete:
        return VK_DELETE;
    case Qt::Key_Pause:
        return VK_PAUSE;
    case Qt::Key_Print:
        return VK_PRINT;
    case Qt::Key_Clear:
        return VK_CLEAR;
    case Qt::Key_Home:
        return VK_HOME;
    case Qt::Key_End:
        return VK_END;
    case Qt::Key_Left:
        return VK_LEFT;
    case Qt::Key_Up:
        return VK_UP;
    case Qt::Key_Right:
        return VK_RIGHT;
    case Qt::Key_Down:
        return VK_DOWN;
    case Qt::Key_PageUp:
        return VK_PRIOR;
    case Qt::Key_PageDown:
        return VK_NEXT;
    case Qt::Key_F1:
        return VK_F1;
    case Qt::Key_F2:
        return VK_F2;
    case Qt::Key_F3:
        return VK_F3;
    case Qt::Key_F4:
        return VK_F4;
    case Qt::Key_F5:
        return VK_F5;
    case Qt::Key_F6:
        return VK_F6;
    case Qt::Key_F7:
        return VK_F7;
    case Qt::Key_F8:
        return VK_F8;
    case Qt::Key_F9:
        return VK_F9;
    case Qt::Key_F10:
        return VK_F10;
    case Qt::Key_F11:
        return VK_F11;
    case Qt::Key_F12:
        return VK_F12;
    case Qt::Key_F13:
        return VK_F13;
    case Qt::Key_F14:
        return VK_F14;
    case Qt::Key_F15:
        return VK_F15;
    case Qt::Key_F16:
        return VK_F16;
    case Qt::Key_F17:
        return VK_F17;
    case Qt::Key_F18:
        return VK_F18;
    case Qt::Key_F19:
        return VK_F19;
    case Qt::Key_F20:
        return VK_F20;
    case Qt::Key_F21:
        return VK_F21;
    case Qt::Key_F22:
        return VK_F22;
    case Qt::Key_F23:
        return VK_F23;
    case Qt::Key_F24:
        return VK_F24;
    case Qt::Key_Space:
        return VK_SPACE;
    case Qt::Key_Asterisk:
        return VK_MULTIPLY;
    case Qt::Key_Plus:
        return VK_ADD;
    case Qt::Key_Comma:
        return VK_SEPARATOR;
    case Qt::Key_Minus:
        return VK_SUBTRACT;
    case Qt::Key_Slash:
        return VK_DIVIDE;
        // numbers
    case Qt::Key_0:
    case Qt::Key_1:
    case Qt::Key_2:
    case Qt::Key_3:
    case Qt::Key_4:
    case Qt::Key_5:
    case Qt::Key_6:
    case Qt::Key_7:
    case Qt::Key_8:
    case Qt::Key_9:
        return key;
        // letters
    case Qt::Key_A:
    case Qt::Key_B:
    case Qt::Key_C:
    case Qt::Key_D:
    case Qt::Key_E:
    case Qt::Key_F:
    case Qt::Key_G:
    case Qt::Key_H:
    case Qt::Key_I:
    case Qt::Key_J:
    case Qt::Key_K:
    case Qt::Key_L:
    case Qt::Key_M:
    case Qt::Key_N:
    case Qt::Key_O:
    case Qt::Key_P:
    case Qt::Key_Q:
    case Qt::Key_R:
    case Qt::Key_S:
    case Qt::Key_T:
    case Qt::Key_U:
    case Qt::Key_V:
    case Qt::Key_W:
    case Qt::Key_X:
    case Qt::Key_Y:
    case Qt::Key_Z:
        return key;
    default:
        return 0;
    }
}

quint32 ScreenShotTool::nativeModifiers(Qt::KeyboardModifiers modifiers)                //mod值转换
{
    quint32 native = 0;
    if (modifiers & Qt::ShiftModifier)
        native |= MOD_SHIFT;
    if (modifiers & Qt::ControlModifier)
        native |= MOD_CONTROL;
    if (modifiers & Qt::AltModifier)
        native |= MOD_ALT;
    if (modifiers & Qt::MetaModifier)
        native |= MOD_WIN;
    return native;
}

bool ScreenShotTool::registerHotKey(Qt::Key key, Qt::KeyboardModifiers modifiers)
{
    const quint32 nativeKey=this->nativeKeycode(key);
    const quint32 nativeModes=this->nativeModifiers(modifiers);
    return RegisterHotKey(0, nativeModes ^ nativeKey, nativeModes, nativeKey);
}

bool ScreenShotTool::unregisterHotKey(Qt::Key key, Qt::KeyboardModifiers modifiers)
{
    const quint32 nativeKey=this->nativeKeycode(key);
    const quint32 nativeModes=this->nativeModifiers(modifiers);
    return UnregisterHotKey(0, nativeModes ^ nativeKey);
}

void ScreenShotTool::slt_changeHotKey(Qt::Key key, Qt::KeyboardModifiers mod)
{
    this->unregisterHotKey(key,mod);
    this->mKey=key;
    this->mMods=mod;
    this->registerHotKey(this->mKey,this->mMods);

    auto strval=this->mpKeystring->key2String(this->mKey,this->mMods);
    OperateSet::writeSetting("HotKey","ScreenShot",strval);
}

void ScreenShotTool::slt_language_set(int index)
{
    if(index==0){
        changeLanguage(Const::L_EN);
    }else if(index==1){
        changeLanguage(Const::L_ZH_CN);
    }
}

void ScreenShotTool::slt_auto_run(int states)
{
    if(Qt::Checked==states){
        this->mIsAutoRun=true;
        OperateSet::writeSetting("Setting","AutoRun",1);
    }else{
        this->mIsAutoRun=false;
        OperateSet::writeSetting("Setting","AutoRun",0);
    }

    this->setAutoRun(this->mIsAutoRun);
}

void ScreenShotTool::slt_AddWindow2Desktop(const QPixmap &pixmap)
{
    auto pWidget=new SimpleWidget(pixmap);
    connect(pWidget,&QObject::destroyed,[=](QObject*){
        disconnect(pWidget);
        mContainSimpleWidget.removeOne(pWidget);
    });
    pWidget->show();
    mContainSimpleWidget.append(pWidget);
}

void ScreenShotTool::setAutoRun(bool sta)
{
    auto pReg=new QSettings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",QSettings::NativeFormat);
    if(sta){
        pReg->setValue("ScreenShot",QApplication::applicationFilePath().replace("/","\\"));
    }else{
        pReg->remove("ScreenShot");
    }
}

void ScreenShotTool::ss_start()
{
    auto pScreen=QGuiApplication::primaryScreen();
    this->mFullPixmap=pScreen->grabWindow(0);
    this->mpScreenCanvas=new Canvas(0);
    connect(this->mpScreenCanvas, SIGNAL(sig_addWindow2Desktop(QPixmap)), this, SLOT(slt_AddWindow2Desktop(QPixmap)));
    connect(this->mpScreenCanvas, &QObject::destroyed, [=](QObject*){
        disconnect(mpScreenCanvas);
    });
    this->mpScreenCanvas->setbgPixmap(this->mFullPixmap);
    auto combox=this->mpUI->comboBox;
    auto id=combox->currentIndex();
    if(0==this->mpUI->comboBox->currentIndex()){
        this->mpScreenCanvas->changeLanguage(Const::L_EN);
    }else if(1==this->mpUI->comboBox->currentIndex()){
        this->mpScreenCanvas->changeLanguage(Const::L_ZH_CN);
    }
}
